﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Diagnostics;
using System.Runtime.Serialization.Formatters.Binary;

namespace ContactsForm.Net
{
    class server
    {

        private int _port;
        //private IPAddress _ip;
        private TcpListener _listener;
        private DataArguments _data = new DataArguments();
        private byte[] _incomingData = new byte[256];
        private List<IPAddress> _ip = new List<IPAddress>();
        //public IEnumerable Data { get; set; }
        public int Port { get { return _port; } }
        public string SData = null;
        /// <summary>
        /// This starts with the initial value of the server and gets updated when the remote Host returns this client's IP Address
        /// </summary>
        //public IPAddress IP { get { return _ip; } }
        //need a read buffer size
        private Byte[] b = new Byte[256];
        //private string data = null;
        //event fires when data is changed
        /// <summary>
        /// Delegate procedure which will handle the event
        /// </summary>
        /// <param name="o"></param>
        /// <param name="args">The arguments provided in the recieved data</param>
        public delegate void DataChangeHandler(DataArguments args);

        //the event
        public event DataChangeHandler DataChanged;

        /// <summary>
        /// Creates and Starts a listening service on the designated port and IP address
        /// </summary>
        /// <param name="port">Port to listen on.  Must between 1024 and 65535</param>
        /// <param name="ip">The IP address to listen on</param>
        public server(int port, IPAddress ip)
        {
            if (port < 1024 || port > 65535)
            {
                throw new ArgumentOutOfRangeException("port", "Value must be be between 1024 and 65535.");
            }
            if (ip == null)
            {
                throw new ArgumentNullException("ip");
            }
            try
            {
                _port = port;
                _ip.Add(ip);
                _listener = new TcpListener(ip, _port);

            }
            catch (SocketException ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.ErrorCode.ToString(), "socket error");
            }
        }

        public ManualResetEvent clientconnected = new ManualResetEvent(false);

        /// <summary>
        /// Listen for client connections
        /// </summary>
        public void listen()
        {
            //clear the event
            clientconnected.Reset();
            _listener.Start();
            Console.WriteLine("Waiting on connections ...");
            //non blocking call to accept requests.
            // need to use ansyc sockets here
            _listener.BeginAcceptTcpClient(new AsyncCallback(listenCallback), _listener);


        }



        public void listenCallback(IAsyncResult a)
        {
            // this is the listen that handles the client
            TcpListener listner = (TcpListener)a.AsyncState;
            // end operation
            TcpClient c = listner.EndAcceptTcpClient(a);
            //process connection
            // data = null;
            // get stream object to read and write
            NetworkStream stream = c.GetStream();
            int i;
            //loop the interface to get data
            // DataArguments args = new DataArguments();
            try
            {
                while ((i = stream.Read(_incomingData, 0, _incomingData.Length)) != 0)
                {
                    //translate
                    SData = System.Text.Encoding.UTF8.GetString(_incomingData, 0, i);
                }
            }
            //    BinaryFormatter bf = new BinaryFormatter();

            //    using (MemoryStream ms = new MemoryStream(_incomingData, 0, _incomingData.Length))
            //        try
            //        {
            //            object temp;
            //            temp = bf.Deserialize(ms);
            //            _data = (DataArguments)temp;
            //        }
            //        catch { return; }
            //}
            catch (System.Runtime.Serialization.SerializationException ex)
            {
                throw ex;
            }

            stream.Close();
            clientconnected.Set();
            try
            {
                if (_data.DataArgs == "IPAdress")
                {
                    _ip.Add(IPAddress.Parse(_data.Data));
                }
                else if (_data.DataArgs == "Remove")
                {
                    _ip.Remove(IPAddress.Parse(_data.Data));
                }
            }
            catch
            {
                throw new InvalidCastException("Couldn't add or remove IPAdress from _ip");
            }
            DataChanged(_data);
        }

        public delegate void Dreceivedata(object sender, DataReceivedEventArgs args);


        public Boolean writetcp()
        {
            return true;
        }

    }



}
